package com.yswy.backstage.authfilter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yswy.backstage.entity.user.User;
import com.yswy.backstage.service.SsoService;
import com.yswy.common.enums.ResultStatus;
import com.yswy.common.model.ResultModel;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;

import javax.annotation.Resource;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

@Order(1)
@WebFilter(filterName = "AuthFilter", urlPatterns = "/*")
public class AuthFilter implements Filter {
    private final Logger log = LoggerFactory.getLogger(this.getClass());

    public static final String ROOT = "4e92a3c21aa46fe075f0965d939090b9";

    private static final String CONNECTOR = "/";

//    public static Map<String, Integer> permissionMap = null;

    private static final Set<String> ALLOWED_PATHS = Collections.unmodifiableSet(new HashSet<>(
            Arrays.asList(
                    "/directory/getServerList",
                    "/sso/requestValidateCode",
                    "/sso/validateCode",
                    "/",
                    "/csrf",
                    "/sso/login",
                    "/sso/logout",
                    "/ding/receive",
                    "/chatTest/chattest",
                    "/chatTest/dataStatistics",
                    "/admin/listMenu",
                    "/api/**",
                    "/admin/getServer",
                    "/sso/sendCode",
                    "/sso/register",
                    "/sso/sendCodeByPwd",
                    "/sso/updatePwd",
                    "/sso/updateByOldPwd",
                    "/test/test",
                    "/doc.html",
                    "/webjars/bycdao-ui/**",
                    "/test/auto/vue_table",
                    "/complaintRecord/callBackVxTs",
                    "/complaintRecord/hHandlingComplaints",
                    "/complaintRecord/complaintNotifications"
            )));

    @Resource
    private SsoService ssoService;

    @Override
    public void init(FilterConfig config) throws ServletException {
        log.info("授权过滤器初始化!");

        ServletContext context = config.getServletContext();
        log.info("不需要认证的 URI：");
        for (String d : ALLOWED_PATHS) {
            log.info(d);
        }
//        permissionMap = ssoService.getAllModelPermission();
//        log.info("权限表：" + permissionMap);

    }

    @Override
    public void destroy() {
        log.info("授权过滤器注销!");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        ObjectMapper mapper = new ObjectMapper();
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        String reqAddress = request.getRemoteAddr();
        log.info(reqAddress + " 安全过滤器：" + req.getRequestURI() + " METHOD:" + req.getMethod());
        String requestURI = req.getRequestURI();
        boolean allowedPath = ALLOWED_PATHS.contains(requestURI);
        if (!allowedPath) {
            allowedPath = requestURI.startsWith("/webjars/bycdao-ui/");
        }
        //跨域设置
        cros(res);
        res.setCharacterEncoding("UTF-8");
        res.setContentType("application/json; charset=utf-8");
        res.setStatus(HttpServletResponse.SC_OK);
        String[] strs = requestURI.split("/");
        String token = "";
        User user = null;

        if (req.getRequestURI().contains("swagger")
                || req.getRequestURI().contains("api")
                || req.getRequestURI().contains("druid")
                || allowedPath) {
            chain.doFilter(req, res);
            return;
        }

        if (strs.length >= 2) {
            token = req.getHeader("Authorization");
            log.info(reqAddress + " Authorization : " + token);
            //更新用户的TOKEN 过期时间，这样用户只要一直有操作，就永远不需要登录。
            user = ssoService.getUserByAuthToken(token);
            req.getSession().setAttribute("user", user);
        }
        if (req.getRequestURI().contains("swagger")
                || req.getRequestURI().contains("api")
                || req.getRequestURI().contains("druid")
                || allowedPath) {
            chain.doFilter(req, res);
            return;
        }
//        if (true) {
//            return;
//        }
        if (StringUtils.isNotBlank(token)) {
            //如果是管理员登录直接跳过验证
            if (ROOT.equals(token)) {
                chain.doFilter(req, res);
                return;
            }
            if (user != null) {
                String model = strs[1];
                String action = strs[2];
                //哪个模块下的哪个请求 e.g. /admin/login
                Set<Integer> userPermissionSet = ssoService.getPermissionMapByUser(user);
                Map<String, Long> userPermissionMap = ssoService.getAllModelPermission();
//                Integer requirePermissionId = userPermissionMap.get(model.concat(CONNECTOR).concat(action));//permissionMap.get(model.concat(CONNECTOR).concat(action));
                Long requirePermissionId = userPermissionMap.get(requestURI);//permissionMap.get(model.concat(CONNECTOR).concat(action));
                if (null != requirePermissionId && CollectionUtils.isNotEmpty(userPermissionSet) && userPermissionSet.contains(Math.toIntExact(requirePermissionId))) {
                    chain.doFilter(req, res);
                    return;
                } else {
                    log.info("current user: {}, do not have right permission！", user.getId());
                    log.info("current user permission：{}", userPermissionSet);
                    log.info("need permission：{}", requirePermissionId);
                }
            }
        }
        if (user == null) {
            res.getWriter().write(mapper.writeValueAsString(ResultModel.error(ResultStatus.LOGIN_OVER)));
        } else {
            res.getWriter().write(mapper.writeValueAsString(ResultModel.error("用户没有正确权限")));
        }
    }

    private HttpServletResponse cros(HttpServletResponse res) {
        res.setHeader("Access-Control-Allow-Origin", "*");
        res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        res.setHeader("Access-Control-Max-Age", "3600");
//        res.setHeader("Access-Control-Allow-Headers", "*");
//        res.setHeader("Authorization", "Authorization");
        res.setHeader("Access-Control-Allow-Headers", "authorization,Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,*");
        res.setStatus(HttpServletResponse.SC_OK);
        return res;
    }

}
